package org.awa.demo.opencv.gltf.newhandler;

import lombok.extern.slf4j.Slf4j;
import org.awa.demo.opencv.bean.gltf.FaceItemDto;
import org.awa.demo.opencv.bean.gltf.GridItemDto;
import org.awa.demo.opencv.bean.gltf.PointItemDto;
import org.awa.demo.opencv.bean.gltf.PrimitiveBean;
import org.awa.demo.opencv.bean.newgltf.NewFaceItemDto;
import org.awa.demo.opencv.bean.newgltf.NewGridItemDto;
import org.awa.demo.opencv.bean.newgltf.NewPointItemDto;
import org.awa.demo.opencv.bean.newgltf.PlaneBean;
import org.awa.demo.opencv.gltf.Constant;
import org.awa.demo.opencv.gltf.SoundUtil;
import org.awa.demo.opencv.gltf.handler.IRectangleHandler;
import org.locationtech.jts.math.Vector3D;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Component
public class NewRectangleAnalysis {

    public NewFaceItemDto getFace(PlaneBean planeBean, INewRectangleHandler rectangleHandler) {
        log.info("cal face name: "+planeBean.getName());

        //统一先X轴，X轴为宽，另一个（Y轴或Z轴为高）。此处用于为基于blender坐标系来说的。
        // 实际就是假设第一个线  point[0,1]为width所在的线，point[1，2]为height所在的线，而pont[0]为起始点

        NewFaceItemDto faceItemDto = new NewFaceItemDto();
        faceItemDto.setName(planeBean.getName());
        faceItemDto.setHandleClass(rectangleHandler == null ? "null" : rectangleHandler.getClass().getSimpleName());
        faceItemDto.setGltfPointList(getPointList(planeBean.getPointList(),false));
        faceItemDto.setBlenderPointList(getPointList(planeBean.getPointListBlender(),false));

        if(rectangleHandler != null){
            List<Vector3D> rectanglePointList = rectangleHandler.getRectanglePointList(planeBean.getPointListBlender());
            faceItemDto.setScopeList(getPointList(rectanglePointList,true));
            int widthSize = getWidthSize(rectanglePointList.get(0),rectanglePointList.get(1));
            int heightSize = getWidthSize(rectanglePointList.get(1),rectanglePointList.get(2));
            faceItemDto.setWidthSize(widthSize);
            List<Vector3D> gridList = rectangleHandler.getGridObject(rectanglePointList,widthSize,heightSize);
            List<NewGridItemDto> gridItemList = new ArrayList<>();
            for (int i = 0; i < gridList.size(); i++) {
                NewGridItemDto gridItemDto = new NewGridItemDto();
                gridItemDto.setIndex(i);

                Vector3D gridPoint = gridList.get(i);
                gridItemDto.setPointCrs(SoundUtil.toGltfCrs(gridPoint));
                log.info("trans crs: "+ SoundUtil.toPointString(gridPoint) + ", gltf: "+SoundUtil.toPointString(gridItemDto.getPointCrs()));
                gridItemList.add(gridItemDto);
            }

            faceItemDto.setGridList(gridItemList);
        }else{
            faceItemDto.setScopeList(new ArrayList<>());
            faceItemDto.setWidthSize(0);
            faceItemDto.setGridList(new ArrayList<>());
        }

        return faceItemDto;
    }

    //根据起止点获取网格数
    private int getWidthSize(Vector3D point1,Vector3D point2){
        log.info("----------- start width size -------------------------");
        log.info("point1 : "+point1.getX() + "," + point1.getY() + "," + point1.getZ());
        log.info("point2 : "+point2.getX() + "," + point2.getY() + "," + point2.getZ());
        //获取两点之间的距离
        double distance = SoundUtil.getDistance(SoundUtil.getPointBean(point1),SoundUtil.getPointBean(point2));
        log.info("distance : "+distance);
        //根据距离和预设的步长长度，获取网格数
        int widthSize = (int) Math.round(distance / Constant.STEP_LENGTH);
        log.info("widthSize : "+widthSize);
        log.info("----------- end width size -------------------------");
        return widthSize;
    }



    //将点列表转换为点对象列表
    private List<NewPointItemDto> getPointList(List<Vector3D> pointList, boolean isGltf){
        return pointList.parallelStream().map(point -> {
            NewPointItemDto pointItemDto = new NewPointItemDto();
            if(isGltf){
                Vector3D gltfPoint = SoundUtil.toGltfCrs(point);
                pointItemDto.setX(gltfPoint.getX());
                pointItemDto.setY(gltfPoint.getY());
                pointItemDto.setZ(gltfPoint.getZ());
            }else{
                pointItemDto.setX(point.getX());
                pointItemDto.setY(point.getY());
                pointItemDto.setZ(point.getZ());
            }
            return pointItemDto;
        }).collect(Collectors.toList());
    }
}
